/**
* AbstractRenderer - Base class for all Renderers
*
* Copyright (c) 2002
* Marty Phelan, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
package com.taursys.xml.render;
import com.taursys.debug.Debug;
import com.taursys.xml.Component;
import com.taursys.xml.Container;
import com.taursys.xml.DocumentComponent;
import com.taursys.xml.event.RenderException;
import com.taursys.dom.DocumentAdapter;
import org.w3c.dom.Node;
import org.w3c.dom.Element;
import org.w3c.dom.Document;
/**
* AbstractRenderer is the base class for all Renderers. It contains common
* behavior for removing(hiding) and restoring(showing) the component.
* @author Marty Phelan
* @version 1.0
*/
public class AbstractRenderer {
private Component component = null;
private boolean removed = false;
private Node componentNode;
private Node parentNode;
private Node siblingNode;
private Document doc;
/**
* Constructs a new AbstractRenderer for the given Component
* @param c Component which owns this renderer
*/
public AbstractRenderer(Component c) {
this.component = c;
}
/**
* Initializes reference to parentNode and siblingNode.
* Only acts if componentNode is null and document has not changed
* @throws RenderException if parent, DocumentAdapter, or Document is null.
*/
protected void init() throws RenderException {
Container parent = component.getParent();
if (parent == null)
throw new RenderException(RenderException.REASON_PARENT_CONTAINER_NULL);
DocumentAdapter da = parent.getDocumentAdapter();
if (da == null)
throw new RenderException(RenderException.REASON_DOCUMENT_IS_NULL);
Document currentDoc = da.getDocument();
if (currentDoc == null)
throw new RenderException(RenderException.REASON_DOCUMENT_IS_NULL);
if (doc != currentDoc) {
doc = currentDoc;
componentNode = null;
}
if (componentNode == null) {
String id = ((DocumentComponent)component).getId();
if (id != null) {
componentNode = component.getParent().getDocumentAdapter().getElementById(
((DocumentComponent)component).getId());
if (componentNode != null) {
parentNode = componentNode.getParentNode();
siblingNode = componentNode.getNextSibling();
} else {
Debug.warn("AbstractRenderer.init: Attempt to render a component which is not in document. ID="
+ ((DocumentComponent)component).getId());
}
} else {
Debug.warn("AbstractRenderer.init: Attempt to render a component whose ID is null. Class="
+ component.getClass().getName());
}
}
}
/**
* Remove self from parent/Document (usually done after all nodes populated).
* Only acts if not already removed (removed=false) and parentNode and
* componentNode are not null. The method reset changes the removed flag
* back to true.
*/
protected void removeSelf() {
if (!removed && parentNode != null && componentNode != null) {
// remove this node from parent node
parentNode.removeChild(componentNode);
// Mark as removed
removed = true;
}
}
/**
* Restore self to parent/Document. Tries to restore to original position
* which is BEFORE the sibling node, otherwise as the first child.
* Only acts if already removed (removed=true)and parentNode and
* componentNode are not null. The method reset changes the removed flag
* to false.
*/
protected void restoreSelf() {
if (removed && parentNode != null && componentNode != null) {
// Add self back BEFORE sibling (keeps original order)
parentNode.insertBefore(componentNode, siblingNode);
// Reset removed flag
removed = false;
}
}
/**
* Get the component node which will be replicated.
* The init method must be invoked before using this method for the first time.
* @return the component node which will be replicated.
*/
protected Node getComponentNode() {
return componentNode;
}
/**
* Get the parent node for the component node.
* The init method must be invoked before using this method for the first time.
* @return the parent node for the component node
*/
public Node getParentNode() {
return parentNode;
}
/**
* Get the sibling node for the component node or null if none. This is the
* sibling that follows the component node.
* The init method must be invoked before using this method for the first time.
* @return the sibling node for the component node or null if none
*/
public Node getSiblingNode() {
return siblingNode;
}
/**
* Get the component for this renderer
* @return the component for this renderer
*/
public Component getComponent() {
return component;
}
/**
* Get the Document for this renderer
* @return the Document for this renderer
*/
public Document getDocument() {
return doc;
}
/**
* Set an indicator of whether or not the master component node has been removed.
* @param b an indicator of whether or not the master component node has been removed.
*/
public void setRemoved(boolean b) {
removed = b;
}
/**
* Get an indicator of whether or not the master component node has been removed.
* @return an indicator of whether or not the master component node has been removed.
*/
public boolean isRemoved() {
return removed;
}
}